/*
 * BrianClarkeCPE301Design4.c
 *
 * Created: 4/5/2014 5:36:09 PM
 *  Author: Iguana
 */ 

#include <avr/io.h>
#include <util/delay.h>

#define F_CPU 8000000UL  // 8 MHz
int flag = 0;						// Break out color loop flag

void init()
	{
	DDRB = 0xFF;					// Set direction for port B to output
	DDRD = 0xFF;					// Set direction for port D to output
	
	TCCR0A = 0xA3;					// Set PWM, Fast PWM
	TCCR1A = 0xA3;					// ...
	TCCR2A = 0xA3;					// ...
	OCR0A = OCR1A = OCR2A = 255;	// Period of timers

	TCCR0B = 0x09;					// Set no pre-scaling
	TCCR1B = 0x19;					// Set no pre-scaling, and CTC
	TCCR2B = 0x09;					// Set no pre-scaling
	OCR0B = OCR1B = OCR2B = 0;		// Duty Cycle
	}

void hueCHANGE()
	{
	flag = 1;						// Break out of each color loop when finished
									// FOR COLOR 1
	while(flag)
		{
		OCR0A--;					// Decrement the period
		if (OCR0A < 26)				// Disallow the period to dip too low
			{
			OCR0A = 255;			// Reset the period when this occurs
			OCR0B++;				// While also incrementing the duty cycle
			}
		if (OCR0B > 230)			// Ensure a 90% maximum duty cycle
			{
			OCR0B = 0;				// Reset the color
			flag = 0;
			}
		}
	_delay_us(240);					// Set a delay for easier viewing
	flag = 1;						// Break out of each color loop when finished
									// FOR COLOR 2
	while(flag)
		{
		OCR1A--;					// Decrement the period
		if (OCR1A < 26)				// Disallow the period to dip too low
			{
			OCR1A = 255;			// Reset the period when this occurs
			OCR1B++;				// While also incrementing the duty cycle
			}	
		if (OCR1B > 230)			// Ensure a 90% maximum duty cycle
			{
			OCR1B = 0;				// Reset the color
			flag = 0;
			}
		}
	_delay_us(240);					// Set a delay for easier viewing
	flag = 1;						// Break out of each color loop when finished
									// FOR COLOR 3
	while(flag)
		{
		OCR2A--;					// Decrement the period
		if (OCR2A < 26)				// Disallow the period to dip too low
			{
			OCR2A = 255;			// Reset the period when this occurs
			OCR2B++;				// While also incrementing the duty cycle
			}
		if (OCR2B > 230)			// Ensure a 90% maximum duty cycle
			{
			OCR2B = 0;				// Reset the color
			flag = 0;
			}
		}
	_delay_us(250);					// Set a delay for easier viewing
	}

	void hueMERGE()
		{
		OCR0B = 230;				// Reset duty cycle to 90% to allow for merging
									// FOR COLOR 1 AND COLOR 2
		while(OCR0B > 0)
			{
			OCR0B--;				// Decrease color 1
			OCR1B++;				// Increase color 2
			}
		_delay_ms(15);				// Set a delay for easier viewing
									// FOR COLOR 2 AND COLOR 3
		while(OCR1B > 0)
			{
			OCR1B--;				// Decrease color 2
			OCR2B++;				// Increase color 3
			}
		_delay_ms(15);				// Set a delay for easier viewing
									// FOR COLOR 3 AND COLOR 1
		while(OCR2B > 0)
			{
			OCR2B--;				// Decrease color 3
			OCR0B++;				// Increase color 1
			}
		_delay_ms(15);				// Set a delay for easier viewing
		}
	
	int main(void)
		{
		init();						// Initialize everything
		while(1)
			{
			hueCHANGE();			// Change colors
			hueMERGE();				// Merge colors
			}
		}